#!/usr/bin/perl
#README!
#I. Informations.
#        so-word-kicking-system, is a good way to enforce correct language on channels.
#
#II. Depencies.
#        Modules Tie::File and Irssi compiled with Perl scripts support.
#
#III. Configuration.
#	You dont need to edit and change values, the script can work defaults, but if you want to then ;-)
#
#	You can modify these settings in Irssi (/set command), or changing settings values.
#	'so_wordbase_path': Defines path to the wordbase with words.
#	'so_enable_logging': Defines events logging. Possible values: 1 = Yes, 0 = No.
#	'so_logfile': This setting is ignored, if 'enable_logging' is set to 0. Defines path to the file, where logs will be stored.
#	'so_channels': Defines channels, where script will be active. Separate them with spaces.
#       'so_notice': Defines notice format about incorrect word. Possible options:
#		%i - replace with incorrect word.
#       	%c - ... correct word.
#               %k - ... channel.
#               %n - ... nick.
#               Example:
#               	You, %n, make a mistake (%i - > %c), on %k.
#
#IV. Executing.
#	Copy script to dir ~/.irssi/scripts/ and run using command in Irssi '/script load so.pl'.
#       If you want to start this script when Irssi is launched copy it to ~/.irssi/scripts/autorun/
#       or better, make a symlink.
#       Script commands:
#	       /so_add <incorrect_word> <correct_word> - adds incorrect and correct word to wordbase.
#              /so_del <bledne_slowo> - removes word from wordbase.
#              /so_info - prints some useful (or not) informations: amount of words in wordbase and time of last reload wordbase (commands above reloads wordbase automatically).
#              /so_reload - reloads wordbase (after manual edition).
#              /so_help - prints help.
#END OF README.

use strict;

use Irssi;
use Tie::File;

use vars qw($VERSION %IRSSI);

$VERSION = "1.0";
%IRSSI = (
        authors => 'Marcin `Conel` Kowalak',
        contact => 'mkconel@gmail.com',
        name => 'SO',
        description => 'Script for enforcing correct langauge.',
        license => "GPLv2",
        changed => "20.08.2006 09:20"
);

#Default settings,
Irssi::settings_add_str('misc', 'so_wordbase_path', "$ENV{'HOME'}/.irssi/scripts/autorun/so.base");
Irssi::settings_add_bool('misc', 'so_enable_logging', 0);
Irssi::settings_add_str('misc', 'so_logfile', "");
Irssi::settings_add_str('misc', 'so_notice', "Illiterate, \%i -> \%c.");
Irssi::settings_add_str('misc', 'so_channels', '#croxx');

our (@base, $last_reload, %channel_statistics) = 0;
$channel_statistics{';;notices'} = 0;
&reload(1);

Irssi::print("SO script loaded, type '/so_help' for help, or read README at beginning script file.");

sub add {
	my ($tekst, $serwer) = @_;
	my @s;
	@s = split(/ /, $tekst, 2);
	if(!$s[0] or !$s[1]) {
		Irssi::print("Usage: so_add <incorrect_word> <correct_word>");
		return;
	}
	$s[0] =~ tr/_'/ /;
	$s[1] =~ tr/_'/ /;
	my $return = &check($s[0]);
	if($return) {
		Irssi::print("Word \"$s[0]\" exist in wordbase.");
		return;
	}
	if($s[0] =~ /;/ || $s[1] =~ /;/) {
	Irssi::print("Invalid mark - \';\'");
	return;
	}
	open(BASE, ">>" . Irssi::settings_get_str('so_wordbase_path')) or Irssi::print("Can't open wordbase: $!");
	print BASE "$s[0];$s[1]\n";
	close BASE;

	Irssi::print("Word \"$s[0]\" will be corrected to \"$s[1]\".");
	&log(my $log = "ADD Word \"$s[0]\" will be corrected to \"$s[1]\".");
	&reload(1);
}

sub del {
	my ($tekst, $serwer) = @_;
	my @s;
	@s = split(/ /, $tekst, 2);
	unless($tekst) {
		Irssi::print("Usage: so_del <incorrect_word>");
		return;
	}
	my $return = &check($tekst);

	unless($return) {
		Irssi::print("Word \"$tekst\" doesn't exist in wordbase.");
		return;
	}
	$tekst =~ tr/_'/ /;
	tie my @base,'Tie::File',"$ENV{'HOME'}/.irssi/scripts/autorun/so.base";
	for my $line (0 .. $#base){
		if($base[$line]=~/^$tekst;\S*/i){
			splice @base,$line,1; last;
		}
	}

	untie @base;
	Irssi::print("Word \"$tekst\" has been remove from wordbase.");
	&log(my $log = "DEL Word \"$tekst\" has been remove from wordbase.");
	&reload(1);
}

sub reload {
	my ($auto) = @_;
	my $count = 0;
	our @base = 0;
	return unless open(BASE, Irssi::settings_get_str('so_wordbase_path')) or Irssi::print("Can't open wordbase: $!");

	while (my $line = <BASE>) {
		$line =~ s/\n//;
		$base[$count] = $line;
		$count++;
	}

	close BASE;

	if(!$auto) {
		Irssi::print("Wordbase reloaded successfully.");
		&log(my $log = "RELOAD Wordbase reloaded successfully.");
	}
	our $last_reload = scalar localtime;
}

sub info {
	my $ilosc = @base;
	Irssi::print("Amount of words in wordbase: $ilosc");
	Irssi::print("Last wordbase reload date: $last_reload.");
	Irssi::print("Total notices: $channel_statistics{';;notices'}.");
	foreach my $line (%channel_statistics) {
		if($line !~ /^\d*$|^;;/) {
			Irssi::print("Channel $line, notices $channel_statistics{$line}.");
		}
	}
}

sub event {
	my ($serwer, $tekst, $nick, $adres) = @_;
	my ($typ, $kanal, @s, $line, $changed_notice) = 0;

	($typ, $tekst) = split(/ /, $tekst, 2);

	return unless ($typ =~ /privmsg/i);
	if($tekst =~ /#\S*/) {
		$kanal = $&;
	}

	$tekst =~ s/$kanal //;
	$tekst =~ s/^://;
	$tekst =~ s/^|$/ /g;

	foreach my $line (@base) {
		@s = split(/;/, $line);

		if($tekst =~ /\s$s[0]\s/i && Irssi::settings_get_str('so_channels') =~ / ?$kanal ?/i) {
			my $changed_notice = Irssi::settings_get_str('so_notice');
			$changed_notice =~ s/\%n/$nick/g;
			$changed_notice =~ s/\%i/$s[0]/g;
			$changed_notice =~ s/\%c/$s[1]/g;
			$changed_notice =~ s/\%k/$kanal/g;
			$serwer->command("/notice $nick $changed_notice");
			&log(my $log = "ORT $nick make a mistake \"$s[0]\", should be \"$s[1]\", on channel $kanal.");
			$channel_statistics{$kanal}++;
			$channel_statistics{';;notices'}++;
			return 0;
		}
	}
}

sub check {
	my ($slowo) = @_;

	open(BASE, Irssi::settings_get_str('so_wordbase_path'));
	while (my $line = <BASE>) {
		return 1 if $line =~ /^$slowo;/i
	}
	close BASE;

	return 0;
}

sub log {
	my ($log) = @_;
	my $czas = scalar localtime;

	return unless Irssi::settings_get_bool('so_enable_logging');

	return unless open(LOG, ">>" . Irssi::settings_get_str('so_logfile')) or Irssi::print("Can't open logfile: $!");

	print LOG "[$czas] $log\n";

	close LOG;
}

sub help {

Irssi::print("
Please see README section at beginning script file!

Commands:
/so_add <incorrect_word> <correct_word> - adds incorrect and correct word to wordbase.
/so_del <bledne_slowo> - removes word from wordbase.
/so_info - prints some useful (or not) informations: amount of words in wordbase and time of last reload wordbase (commands above reloads wordbase automatically).
/so_reload - reloads wordbase (after manual edition).
/so_help - prints this help.
");
}

Irssi::signal_add_last("server event", "event");
Irssi::command_bind( so_add => \&add );
Irssi::command_bind( so_del => \&del );
Irssi::command_bind( so_info => \&info );
Irssi::command_bind( so_reload => \&reload );
Irssi::command_bind( so_help => \&help);
